home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 8 / QRZ Ham Radio Callsign Database - Volume 8.iso / mac / files / t_sys5 / unixcpio.gz / unixnet.cpio / pktdrvr.c < prev    next >
C/C++ Source or Header  |  1994-07-11  |  8KB  |  337 lines

  1. /* Driver for FTP Software's packet driver interface */
  2. #include <stdio.h>
  3. #include "global.h"
  4. #include "mbuf.h"
  5. #include "enet.h"
  6. #include "iface.h"
  7. #include "ec.h"
  8. #include "timer.h"
  9. #include "arp.h"
  10. #include "trace.h"
  11. #include "regs.h"
  12. #include "pktdrvr.h"
  13.  
  14. struct pktdrvr pktdrvr[PK_MAX];
  15. unsigned int npk;
  16. int derr;
  17.  
  18. /* Send raw packet (caller provides header) */
  19. int
  20. pk_raw(interface,bp)
  21. struct interface *interface;    /* Pointer to interface control block */
  22. struct mbuf *bp;        /* Data field */
  23. {
  24.     register struct pktdrvr *pp;
  25.     int16 size;
  26.     struct mbuf *bp1;
  27.  
  28.     pp = &pktdrvr[interface->dev];
  29.     size = len_mbuf(bp);
  30.  
  31.     switch(pp->class){
  32.     case ETHERNET:
  33.         dump(interface,IF_TRACE_OUT,TRACE_ETHER,bp);
  34.         if(size < 60)
  35.             size = 60;
  36.         break;
  37.     case SERIAL_LINE:
  38.         dump(interface,IF_TRACE_OUT,TRACE_IP,bp);
  39.         break;
  40.     }
  41.     if(bp->next != NULLBUF){
  42.         /* Copy to contiguous buffer, since driver can't handle mbufs */
  43.         bp1 = copy_p(bp,size);
  44.         free_p(bp);
  45.         bp = bp1;
  46.         if(bp == NULLBUF)
  47.             return -1;
  48.     } else
  49.         bp->cnt = size;    /* Make sure packet size is big enough */
  50.  
  51.     send_pkt(pp->intno,bp->data,bp->cnt);
  52.     free_p(bp);
  53.     return 0;
  54. }
  55.  
  56. /* Packet driver receive routine. Called from an assembler hook that pushes
  57.  * the caller's registers on the stack so we can access and modify them.
  58.  * This is a rare example of call-by-location in C.
  59.  */
  60. int
  61. pkint(di,si,bp,dx,cx,bx,ax,ds,es)
  62. unsigned short di,si,bp,dx,cx,bx,ax,ds,es;
  63. {
  64.     register struct pktdrvr *pp;
  65.     int i;
  66.  
  67.     for(i=0,pp = &pktdrvr[0];i < npk;i++,pp++)
  68.         if(pp->handle1 == bx
  69.          || (pp->class == ETHERNET && pp->handle2 == bx))
  70.             break;
  71.     if(i == npk)
  72.         return;    /* Unknown packet */
  73.  
  74.     switch(ax){
  75.     case 0:    /* Space allocate call */
  76.         if(pp->rcvcnt < pp->rcvmax && (pp->buffer = alloc_mbuf(cx)) != NULLBUF){
  77.             es = FP_SEG(pp->buffer->data);
  78.             di = FP_OFF(pp->buffer->data);
  79.             pp->buffer->cnt = cx;
  80.         } else {
  81.             es = di = 0;
  82.         }
  83.         break;
  84.     case 1:    /* Packet complete call */
  85.         enqueue(&pp->rcvq,pp->buffer);
  86.         pp->rcvcnt++;
  87.         pp->buffer = NULLBUF;
  88.         break;
  89.     default:
  90.         break;
  91.     }
  92. }
  93. /* Process any incoming packets on the receive queue */
  94. void
  95. pk_recv(interface)
  96. struct interface *interface;
  97. {
  98.     void arp_input();
  99.     int ip_route();
  100.     struct pktdrvr *pp;
  101.     struct mbuf *bp;
  102.  
  103.     pp = &pktdrvr[interface->dev];
  104.     if((bp = dequeue(&pp->rcvq)) == NULLBUF)
  105.         return;
  106.  
  107.     pp->rcvcnt--;
  108.     switch(pp->class){
  109.     case ETHERNET:
  110.         dump(interface,IF_TRACE_IN,TRACE_ETHER,bp);
  111.         eproc(interface,bp);
  112.         break;
  113.     case SERIAL_LINE:
  114.         dump(interface,IF_TRACE_IN,TRACE_IP,bp);
  115.         ip_route(bp,0);
  116.         break;
  117.     }
  118. }
  119. /* Shut down the packet interface */
  120. pk_stop(interface)
  121. struct interface *interface;
  122. {
  123.     struct pktdrvr *pp;
  124.  
  125.     pp = &pktdrvr[interface->dev];
  126.     /* Call driver's release_type() entry */
  127.     if(release_type(pp->intno,pp->handle1) == -1)
  128.         printf("%s: release_type error code %u\n",interface->name,derr);
  129.  
  130.     if(pp->class == ETHERNET)
  131.         release_type(pp->intno,pp->handle2);
  132. }
  133. /* Attach a packet driver to the system
  134.  * argv[0]: hardware type, must be "packet"
  135.  * argv[1]: software interrupt vector, e.g., x7e
  136.  * argv[2]: interface label, e.g., "trw0"
  137.  * argv[3]: maximum number of packets allowed on receive queue, e.g., "5"
  138.  * argv[4]: maximum transmission unit, bytes, e.g., "1500"
  139.  */
  140. pk_attach(argc,argv)
  141. int argc;
  142. char *argv[];
  143. {
  144.     register struct interface *if_pk;
  145.     extern struct interface *ifaces;
  146.     int class;
  147.     unsigned int intno;
  148.     void pkvec();
  149.     static char iptype[] = {IP_TYPE >> 8,IP_TYPE};
  150.     static char arptype[] = {ARP_TYPE >> 8,ARP_TYPE};
  151.     int pether(),gaether(),enet_send(),enet_output(),slip_send();
  152.     void (*getvect())();
  153.     long drvvec;
  154.     char sig[8];    /* Copy of driver signature "PKT DRVR" */
  155.     register struct pktdrvr *pp;
  156.  
  157.     if(npk >= PK_MAX){
  158.         printf("Too many packet drivers\n");
  159.         return -1;
  160.     }
  161.  
  162.     intno = htoi(argv[1]);
  163.     /* Verify that there's really a packet driver there, so we don't
  164.      * go off into the ozone (if there's any left)
  165.      */
  166.     drvvec = (long)getvect(intno);
  167.     movblock((unsigned short)drvvec+3, (unsigned short)(drvvec >> 16),
  168.         sig,getds(),strlen(PKT_SIG));
  169.     if(strncmp(sig,PKT_SIG,strlen(PKT_SIG)) != 0){
  170.         printf("No packet driver loaded at int 0x%x\n",intno);
  171.         return -1;
  172.     }
  173.     if((if_pk = (struct interface *)calloc(1,sizeof(struct interface))) == NULLIF
  174.      ||(if_pk->name = malloc((unsigned)strlen(argv[2])+1)) == NULLCHAR){
  175.         if(if_pk != NULLIF)
  176.             free((char *)if_pk);
  177.         printf("pk_attach: no memory!\n");
  178.         return -1;
  179.     }
  180.     pp = &pktdrvr[npk];
  181.     strcpy(if_pk->name,argv[2]);
  182.     pp->rcvmax = atoi(argv[3]);
  183.     if_pk->mtu = atoi(argv[4]);
  184.     if_pk->dev = npk++;
  185.     if_pk->raw = pk_raw;
  186.     if_pk->recv = pk_recv;
  187.     if_pk->stop = pk_stop;
  188.     pp->intno = intno;
  189.  
  190.     /* Find out by exhaustive search what class this driver is (ugh) */
  191.     for(class=0;class<9;class++){
  192.         pp->handle1 = access_type(intno,class,ANYTYPE,0,NULLCHAR,0,pkvec);
  193.         if(pp->handle1 != -1)
  194.             break;
  195.     }
  196.     /* Now that we know, release it and do it all over again with the
  197.      * right type fields
  198.      */
  199.     release_type(intno,pp->handle1);
  200.     switch(class){
  201.     case ETHERNET:
  202.         pp->handle1 = access_type(intno,class,ANYTYPE,0,iptype,2,pkvec);
  203.         pp->handle2 = access_type(intno,class,ANYTYPE,0,arptype,2,pkvec);            
  204.         if_pk->send = enet_send;
  205.         if_pk->output = enet_output;
  206.         /* Get hardware Ethernet address from driver */
  207.         if_pk->hwaddr = malloc(EADDR_LEN);
  208.         get_address(intno,pp->handle1,if_pk->hwaddr,EADDR_LEN);
  209.         arp_init(ARP_ETHER,EADDR_LEN,IP_TYPE,ARP_TYPE,ether_bdcst,pether,gaether);
  210.         break;
  211.     case SERIAL_LINE:
  212.         pp->handle1 = access_type(intno,class,ANYTYPE,0,NULLCHAR,0,pkvec);
  213.         if_pk->send = slip_send;
  214.         break;
  215.     default:
  216.         printf("Packet driver has unsupported class %u\n",class);
  217.         free(if_pk->name);
  218.         free((char *)if_pk);
  219.         npk--;
  220.         return -1;
  221.     }
  222.     pp->class = class;
  223.     if_pk->next = ifaces;
  224.     ifaces = if_pk;
  225.  
  226.     return 0;
  227. }
  228. static int
  229. access_type(intno,if_class,if_type,if_number,type,typelen,receiver)
  230. int intno;
  231. int if_class;
  232. int if_type;
  233. int if_number;
  234. char *type;
  235. unsigned typelen;
  236. void (*receiver)();
  237. {
  238.     struct regs regs;
  239.  
  240.     _AH = ACCESS_TYPE;    /* Access_type() function */
  241.     _AL = if_class;        /* Class */
  242.     _BX = if_type;            /* Type */
  243.     _DL = if_number;        /* Number */
  244.     /* Packet type template */
  245.     _DS = FP_SEG(type);
  246.     _SI = FP_OFF(type);
  247.     _CX = typelen;            /* Length of type */
  248.     /* Address of receive handler */
  249.     _ES = FP_SEG(receiver);
  250.     _DI = FP_OFF(receiver);
  251.     if(sysint(intno,®s,®s) & FLAG_CARRY){
  252.         derr = _DH;
  253.         return -1;
  254.     } else
  255.         return _AX;
  256. }
  257. static int
  258. release_type(intno,handle)
  259. int intno;
  260. int handle;
  261. {
  262.     struct regs regs;
  263.  
  264.     _AH = RELEASE_TYPE;
  265.     _BX = handle;
  266.     if(sysint(intno,®s,®s) & FLAG_CARRY){
  267.         derr = _DH;
  268.         return -1;
  269.     } else
  270.         return 0;
  271. }
  272. static int
  273. send_pkt(intno,buffer,length)
  274. int intno;
  275. char *buffer;
  276. unsigned length;
  277. {
  278.     struct regs regs;
  279.  
  280.     _AH = SEND_PKT;
  281.     _DS = FP_SEG(buffer);
  282.     _SI = FP_OFF(buffer);
  283.     _CX = length;
  284.     if(sysint(intno,®s,®s) & FLAG_CARRY){
  285.         derr = _DH;
  286.         return -1;
  287.     } else
  288.         return 0;
  289. }
  290. static int
  291. driver_info(intno,handle,version,class,type,number,basic)
  292. int intno;
  293. int handle;
  294. int *version,*class,*type,*number,*basic;
  295. {
  296.     struct regs regs;
  297.  
  298.     _AH = DRIVER_INFO;
  299.     _AL = 0xff;
  300.     _BX = handle;
  301.     if(sysint(intno,®s,®s) & FLAG_CARRY){
  302.         derr = _DH;
  303.         return -1;
  304.     }
  305.     if(version != NULL)
  306.         *version = _BX;
  307.     if(class != NULL)
  308.         *class = _CH;
  309.     if(type != NULL)
  310.         *type = _DX;
  311.     if(number != NULL)
  312.         *number = _CL;
  313.     if(basic != NULL)
  314.         *basic = _AL;
  315.     return 0;
  316. }
  317. static int
  318. get_address(intno,handle,buf,len)
  319. int intno;
  320. int handle;
  321. char *buf;
  322. int len;
  323. {
  324.     struct regs regs;
  325.  
  326.     _AH = GET_ADDRESS;
  327.     _BX = handle;
  328.     _ES = FP_SEG(buf);
  329.     _DI = FP_OFF(buf);
  330.     _CX = len;
  331.     if(sysint(intno,®s,®s) & FLAG_CARRY){
  332.         derr = _DH;
  333.         return -1;
  334.     }
  335.     return 0;
  336. }
  337.